﻿namespace TuneMultiCheckBox.BusinessLogic
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Entities;
    using Microsoft.Crm.Sdk.Messages;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Messages;
    using Microsoft.Xrm.Sdk.Metadata;
    using Utils;

  /// <summary>
  /// Base class for entity manager classes
  /// </summary>
  /// <typeparam name="T">Entity</typeparam>
  public class ManagerBase<T> where T : Entity, new()
  {
    protected readonly PluginBase<T>.LocalPluginContext LocalContext;

    /// <summary>
    /// Gets or sets the target validators.
    /// </summary>
    /// <value>
    /// The target validators.
    /// </value>
    private static readonly Dictionary<MessageName, Action<PluginBase<T>.LocalPluginContext>> TargetValidators;

    /// <summary>
    /// Initializes static members of the <see cref="ManagerBase{T}"/> class. 
    /// </summary>
    static ManagerBase()
    {
      TargetValidators = new Dictionary<MessageName, Action<PluginBase<T>.LocalPluginContext>>
      {
         { MessageName.Create, ValidateTargetEntity },
         { MessageName.Update, ValidateTargetEntity },
         { MessageName.Delete, ValidateTargetEntityReference }
      };
    }

    /// <summary>
    /// Initializes a new instance of the <see cref="ManagerBase{T}" /> class.
    /// </summary>
    /// <param name="localContext">The local context.</param>
    public ManagerBase(PluginBase<T>.LocalPluginContext localContext)
    {
      this.LocalContext = localContext;
    }

    /// <summary>
    /// Validates the context.
    /// </summary>
    /// <exception cref="System.NullReferenceException">Local Context</exception>
    protected void ValidateContext()
    {
      if (this.LocalContext == null)
      {
        throw new NullReferenceException("this.LocalContext");
      }
    }

    /// <summary>
    /// Validates the target.
    /// </summary>
    protected void ValidateTarget()
    {
      var messageName = this.LocalContext.PluginExecutionContext.MessageName;
      MessageName message;
      if (!Enum.TryParse(messageName, true, out message))
      {
        return;
      }

      if (!TargetValidators.ContainsKey(message))
      {
        return;
      }

      var targetValidator = TargetValidators[message];
      targetValidator(this.LocalContext);
    }

    /// <summary>
    /// Validates the form required fields.
    /// </summary>
    /// <param name="extendedEntity">The extended entity.</param>
    protected virtual void ValidateFormRequiredFields(ExtendedEntity<T> extendedEntity)
    {
      
    }


    /// <summary>
    /// Validates the target entity.
    /// </summary>
    /// <param name="localContext">The local context.</param>
    private static void ValidateTargetEntity(PluginBase<T>.LocalPluginContext localContext)
    {
      if (localContext.InputTarget == null)
      {
        throw new NullReferenceException("InputTargetEntity");
      }
    }

    /// <summary>
    /// Validates the target entity reference.
    /// </summary>
    /// <param name="localContext">The local context.</param>
    private static void ValidateTargetEntityReference(PluginBase<T>.LocalPluginContext localContext)
    {
      if (localContext.InputTargetEntityReference == null)
      {
        throw new NullReferenceException("InputTargetEntityReference");
      }
    }
  }
}
